#include "XVideoThread.h"

XVideoThread::XVideoThread()
{
	mutex.lock();
	isExit = false;
	mutex.unlock();
	start();

}


XVideoThread::~XVideoThread()
{
	mutex.lock();
	isExit = true;
	mutex.unlock();
}
//线程入口函数
//启动线程后，一直在循环遍历等待cap1被打开
// 失败  跳出循环   成功 开始读帧解码  颜色转换
//添加休眠的作用是使当前线程 防止占满cpu ，因为一直遍历会抢夺cpu资源
//这里通过信号槽将数据发送给XVideoWidget 进行渲染
void XVideoThread::run()
{
	Mat mat1;
	while (true)
	{
		mutex.lock();
		if (isExit) {
		
			mutex.unlock();
			break;
		}
		if (!cap1.isOpened())// 视频是否打开，是临界代码，其他线程可能打开了，所以需要当前执行完
		{
			mutex.unlock();
			msleep(5);
			continue;
		}
		if (!cap1.read(mat1)|| mat1.empty())
		{
			mutex.unlock();
			msleep(5);
			continue;
		}
		//发送包含mat的数据
		ViewImage1(mat1);
		msleep(durationPer);
		mutex.unlock();
	}


}
double XVideoThread::getPos()
{
	double pos = 0.0;
	mutex.lock();
	if (!cap1.isOpened())
	{
		mutex.unlock();
		return pos;
	}
	double count = cap1.get(CAP_PROP_FRAME_COUNT);
	double current = cap1.get(CAP_PROP_POS_FRAMES);
	if (count >0.001)
	{
		pos = current / count;
	}
	mutex.unlock();
	return pos;
}
//由pushbutton调用
//加锁，其他线程会阻塞 访问不到临界区代码 
//只有当cap1.open 执行完毕后再释放，其他线程也可以再执行了
bool XVideoThread::openVideo(const std::string fileName)
{
	mutex.lock();
	bool rec = cap1.open(fileName);
	std::cout << rec << std::endl;
	mutex.unlock();
	if (rec)
	{
		fps = cap1.get(CAP_PROP_FPS);
		if (fps <=0)
		{
			fps = 25;
		}
		durationPer = 1000 / fps;
		std::cout <<"durationPer:"<< durationPer << std::endl;

	}
	return rec;
}

//滑动到某一位置
bool XVideoThread::seek(int frame)
{
	mutex.lock();
	if (!cap1.isOpened())
	{
		mutex.unlock();
		return false;
	}
	int rec = cap1.set(CAP_PROP_POS_FRAMES,frame);
	mutex.unlock();
	return rec;
}

bool XVideoThread::seek(double frame)
{
	double count = cap1.get(CAP_PROP_FRAME_COUNT);
	int mFrame = frame*count;//通过进度条位置 （0-1） * 总帧数 确定滑动的精确帧数位置
	//这里不用考虑滑动到的是否是关键帧  ，opencv已经处理  原理是通过遍历获取关键帧然后显示
	
	return seek(mFrame);
}
